package ikelib;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.LinkedList;


public class drawTools {
	public static final int POSITION_LEFT_TOP = 0;
	public static final int POSITION_CENTER_TOP = 1;
	public static final int POSITION_RIGHT_TOP = 2;
	public static final int POSITION_RIGHT_CENTER = 3;
	public static final int POSITION_RIGHT_BASELINE = 4;
	public static final int POSITION_RIGHT_BOTTOM = 5;
	public static final int POSITION_CENTER_BOTTOM = 6;
	public static final int POSITION_LEFT_BOTTOM = 7;
	public static final int POSITION_LEFT_BASELINE = 8;
	public static final int POSITION_LEFT_CENTER = 9;
	public static final int FILL_RECT	= 1 << 4; // テキストの矩形をクリアする
	
	drawTools(){
	}
	/**
	 * 指定の位置を基準にしてテキストを書く
	 * @param g
	 * @param mes
	 * @param x
	 * @param y
	 * @param position  <BR>
	 * POSITION_LEFT_TOP = 0; <BR>
	 * POSITION_CENTER_TOP = 1;<BR>
	 * POSITION_RIGHT_TOP = 2;<BR>
	 * POSITION_RIGHT_CENTER = 3;<BR>
	 * POSITION_RIGHT_BASELINE = 4;<BR>
	 * POSITION_RIGHT_BOTTOM = 5;<BR>
	 * POSITION_CENTER_BOTTOM = 6;<BR>
	 * POSITION_LEFT_BOTTOM = 7;<BR>
	 * POSITION_LEFT_BASELINE = 8;<BR>
	 * POSITION_LEFT_CENTER = 9;<BR>
	 * FILL_RECT	= 1 << 4; // テキストの矩形をクリアする
	 */
	public static void drawText(Graphics g,String mes,int x,int y,int position){
		FontMetrics fm = g.getFontMetrics();
		//LineMetrics lm = fm.getLineMetrics(mes,g);
		switch(position&0xf){
		case POSITION_LEFT_TOP:	// 左上
			y += fm.getAscent();
			break;
		case POSITION_CENTER_TOP:	// 上中
			x -= fm.stringWidth(mes)/2;
			y += fm.getAscent();
			break;
		case POSITION_RIGHT_TOP:	// 右上
			x -= fm.stringWidth(mes);
			y += fm.getAscent();
			break;
		case POSITION_RIGHT_CENTER:	// 右中
			x -= fm.stringWidth(mes);
			y += (fm.getHeight()/2 -fm.getDescent());
			break;
		case POSITION_RIGHT_BASELINE:	// 右ベースライン
			x -= fm.stringWidth(mes);
			break;
		case POSITION_RIGHT_BOTTOM:	// 右下
			x -= fm.stringWidth(mes);
			y -= fm.getDescent();
			break;
		case POSITION_CENTER_BOTTOM:	// 下中
			x -= fm.stringWidth(mes)/2;
			y -= fm.getDescent();
			break;
		case POSITION_LEFT_BOTTOM:	// 左下
			y -= fm.getDescent();
			break;
		case POSITION_LEFT_BASELINE:	// 左ベースライン
			break;
		case POSITION_LEFT_CENTER:	// 左中
		default:	
			y += (fm.getHeight()/2 -fm.getDescent());
		}
		if((position & FILL_RECT) != 0){
			int yf1 = y - fm.getHeight() + fm.getDescent();
			g.clearRect(x-1, yf1-1,fm.stringWidth(mes)+2 ,fm.getHeight()+2 );
		}
		g.drawString(mes,x,y);
	}
	/**
	 * 指定の位置を基準にしてテキストを書く (回転つき）
	 * @param g
	 * @param mes
	 * @param x
	 * @param y
	 * @param position
	 * @param theta 右回りにラジアンで指定
	 */
	public static void drawText(Graphics2D g,String mes,int x,int y,int position,double theta){
		int x1=x;
		int y1=y;
		FontMetrics fm = g.getFontMetrics();
		switch(position&0xf){
		case POSITION_LEFT_TOP:	// 左上
			y += fm.getAscent();
			break;
		case POSITION_CENTER_TOP:	// 上中
			x -= fm.stringWidth(mes)/2;
			y += fm.getAscent();
			break;
		case POSITION_RIGHT_TOP:	// 右上
			x -= fm.stringWidth(mes);
			y += fm.getAscent();
			break;
		case POSITION_RIGHT_CENTER:	// 右中
			x -= fm.stringWidth(mes);
			y += (fm.getHeight()/2 -fm.getDescent());
			break;
		case POSITION_RIGHT_BASELINE:	// 右ベースライン
			x -= fm.stringWidth(mes);
			break;
		case POSITION_RIGHT_BOTTOM:	// 右下
			x -= fm.stringWidth(mes);
			y -= fm.getDescent();
			break;
		case POSITION_CENTER_BOTTOM:	// 下中
			x -= fm.stringWidth(mes)/2;
			y -= fm.getDescent();
			break;
		case POSITION_LEFT_BOTTOM:	// 左下
			y -= fm.getDescent();
			break;
		case POSITION_LEFT_BASELINE:	// 左ベースライン
			break;
		case POSITION_LEFT_CENTER:	// 左中
		default:	
			y += (fm.getHeight()/2 -fm.getDescent());
		}
		Graphics2D g2 = (Graphics2D)g.create();
		g2.rotate(theta,(double)x1,(double)y1);
		g2.drawString(mes,x,y);
		g2.dispose();
	}
	
	/**
	 * テキストを描画するサイズを返す。
	 * 
	 * @param g2
	 * @param s
	 * @return
	 */
	public static Dimension textSize(Graphics2D g2,String s){
		FontMetrics fm = g2.getFontMetrics();
		Dimension ret = new Dimension(fm.stringWidth(s),fm.getHeight());
		return ret;
	}
	/**
	 * テキストを描画するサイズを返す。
	 * 
	 * @param g2
	 * @param s
	 * @param virtical　文字列を垂直方向に配置する。（幅は最大値、高さは合計）
	 * @return
	 */
	public static Dimension textSize(Graphics2D g2,LinkedList<String> s,boolean virtical){
		FontMetrics fm = g2.getFontMetrics();
		int x1 = 0;
		int y1 = 0;
		for(String str : s){
			int x = fm.stringWidth(str);
			int y = fm.getHeight();
			if(virtical){
				if(x1<x) x1=x;
				y1 += y;
			}
			else{
				x1 += x;
				if(y1<y) y1=y;
			}
		}
		return new Dimension(x1,y1);
	}
	
	/**
	 * 文字列の配列を縦にレイアウトして表示する
	 * 
	 * @param g2
	 * @param m
	 * @param x
	 * @param y
	 * @param pos
	 */
	public static Rectangle drawText(Graphics2D g2, LinkedList<String> m, int x,	int y, int pos, boolean virtical) {
		Dimension dm = textSize(g2,m,virtical);
		FontMetrics fm = g2.getFontMetrics();
		switch(pos&0xf){
		case POSITION_LEFT_TOP:	// 左上
			y += (dm.height-fm.getDescent());
			break;
		case POSITION_CENTER_TOP:	// 上中
			x -= dm.width/2;
			y += (dm.height-fm.getDescent());
			break;
		case POSITION_RIGHT_TOP:	// 右上
			x -= dm.width;
			y += (dm.height-fm.getDescent());
			break;
		case POSITION_RIGHT_CENTER:	// 右中
			x -= dm.width;
			y += (dm.height/2 - fm.getDescent());
			break;
		case POSITION_RIGHT_BASELINE:	// 右ベースライン
			x -= dm.width;
			break;
		case POSITION_RIGHT_BOTTOM:	// 右下
			x -= dm.width;
			y -= fm.getDescent();
			break;
		case POSITION_CENTER_BOTTOM:	// 下中
			x -= dm.width/2;
			y -= fm.getDescent();
			break;
		case POSITION_LEFT_BOTTOM:	// 左下
			y -= fm.getDescent();
			break;
		case POSITION_LEFT_BASELINE:	// 左ベースライン
			break;
		case POSITION_LEFT_CENTER:	// 左中
		default:	
			y += (dm.height/2 -fm.getDescent());
		}
		// 下地をクリアするかどうか
		Rectangle rec = new Rectangle(x,y - dm.height+fm.getDescent()+fm.getLeading(),dm.width,dm.height);
		if((pos & FILL_RECT) != 0){
			g2.clearRect(rec.x,rec.y,rec.width,rec.height);
		}
		// 文字列を書く
		int line = m.size();
		int h = dm.height/line;
		y -= (line-1)*h;
		for(int i=0;i<line;i++){
			g2.drawString(m.get(i),x,y);
			y+=h;
		}
		// 文字列を囲むサイズを返す。
		return rec;
	}

	/**
	 * compの大きさにちょうど収まるように中間を省略したテキストを返す
	 * @param text
	 * @param comp
	 * @return　
	 */
	public static String trancateString(String text,Component comp){
		int width = comp.getWidth();
		FontMetrics fm = comp.getFontMetrics(comp.getFont());
		int cw = fm.stringWidth(text);
		if(cw > width){
			int len = text.length();
			int remove = (int)((float)(cw - width)/(float)cw*(float)len); 
			remove += 4;
			String s1 = text.substring(0,len/2 - (remove/2));
			String s2 = text.substring(len/2 + (remove/2),len);
			text = s1 + "..." + s2;
		}
		return text;
	}
	/**
	 * 数値を時間表示文字列にする。 1.2 us / 59:12.123 
	 * @param us マイクロ秒
	 * @return　
	 */
	public static String timeSpanString(float us){
		String ret = null;
		boolean sig = true;
		if(us < 0.0f){
			us *= -1.0f;
			sig = false;
		}
		if(us<1000f){ // 999マイクロ秒まで
			ret = String.format("%3.0f us", us);
		}
		else if(us <1000f * 1000f){ // 999ミリ秒まで
			ret = String.format("%6.3f ms", us/1000f);
		}
		else if(us <= (60f * 1000f * 1000f)){ // 59秒まで
			ret = String.format("%6.3f s", us/(1000f*1000f));
		}
		else if(us <= (60f * 60f * 1000f * 1000f)){ // 59分まで
			int min = (int)(us / (60f * 1000f* 1000f));
			us -= ((float)min * 60f * 1000f* 1000f);
			ret = String.format("%d:%-6.3f", min,us/(1000f*1000f));
		}
		else { //
			int hour = (int)(us / (60f * 60f * 1000f* 1000f));
			us -= ((float)hour * 60f * 60f * 1000f* 1000f);
			int min = (int)(us / (60f * 1000f* 1000f));
			us -= ((float)min * 60f * 1000f* 1000f);
			ret = String.format("%d:%d:%-6.3f", hour,min,us/(1000f*1000f));
		}
		if(!sig) ret = "-"+ret;
		return ret;
	}
	/**
	 * 周期（マイクロ秒）を周波数表示文字列にする。 1.5 kHz 
	 * @param us
	 * @return
	 */
	public static String freqString(float us){
		if(us<0f) us *= -1f;
		String ret = null;
		float freq =  1000000f/us;
		if(freq < 1f){
			ret = String.format("%6.3f mHz", freq*1000f);
		}
		else if(freq < 1000f){
			ret = String.format("%6.3f Hz", freq);
		}
		else {
			ret = String.format("%6.3f kHz", freq/1000f);
		}
		return ret;
	}
	/**
	 * doubleな数値を与えて、ＳＩ接頭語付きのフォーマットされた文字列を得る　<BR>
	 * 
	 * 
	 * @param val　表示したい値
	 * @param base　"%f" などのフォーマット文字列
	 * @return　
	 */
	public static String prefixString(double val,String base){
		String ret = null;
		double valabs = Math.abs(val);
		if(valabs>=1e15){
			ret = String.format("%e", val);
		}
		else if(valabs>=1e12){
			ret = String.format(base + "T", val/1e12);
		}
		else if(valabs>=1e9){
			ret = String.format(base + "G", val/1e9);
		}
		else if(valabs>=1e6){
			ret = String.format(base + "M", val/1e6);
		}
		else if(valabs>=1e3){
			ret = String.format(base + "K", val/1e3);
		}
		else if(valabs>=1){
			ret = String.format(base + "", val);
		}
		else if(valabs>=1e-3){
			ret = String.format(base + "m", val*1e3);
		}
		else if(valabs>=1e-6){
			ret = String.format(base + "u", val*1e6);
		}
		else if(valabs>=1e-9){
			ret = String.format(base + "n", val*1e9);
		}
		else if(valabs>=1e-12){
			ret = String.format(base + "p", val*1e12);
		}
		else if(valabs>=1e-15){
			ret = String.format(base + "f", val*1e15);
		}
		else{
			ret = String.format("%.1e", val);
		}
		return ret;
	}
}
